//@version=6
// @author Andy Storm | AI-StormCore
indicator("StormCore | SMC, Div & ST+ Master v2.0", shorttitle="SC | Master v2.0", overlay=true, max_boxes_count=100, max_lines_count=500, max_labels_count=500, max_bars_back=4000)

// ==============================================================================
// ━━━ MASTER MODULE TOGGLES ━━━
// ==============================================================================
grp_master = "━━━ MASTER MODULE TOGGLES ━━━"
bool show_mod_st  = input.bool(true, "Enable SuperTrend Module", group=grp_master, tooltip="Включает расчеты и отображение линий SuperTrend.")
bool show_mod_smc = input.bool(true, "Enable SMC Module", group=grp_master, tooltip="Включает зоны FVG, OB и CHoCH старшего таймфрейма.")
bool show_mod_div = input.bool(true, "Enable Divergence Module", group=grp_master, tooltip="Включает поиск и отрисовку дивергенций.")

// ==============================================================================
// ━━━ SUPERTREND MODULE SETTINGS ━━━
// ==============================================================================
grp_st_mode = "━━━ ST: OPERATING MODE ━━━"
grp_st_man  = "━━━ ST: MANUAL SETTINGS ━━━"
grp_st_disp = "━━━ ST: DISPLAY & ALERTS ━━━"

string MODE_AUTO = "StormCore Auto (TF Optimized)"
string MODE_MAN  = "StormCore Manual Override"
string MA_SMA = "SMA", string MA_EMA = "EMA", string MA_WMA = "WMA", string MA_VWMA = "VWMA", string MA_VAWMA = "VAWMA"

string in_st_opMode = input.string(MODE_AUTO, title="Operating Mode", options=[MODE_AUTO, MODE_MAN], group=grp_st_mode, tooltip="Auto adapts settings based on the SELECTED timeframe below.")
string in_st_tf     = input.timeframe("", title="SuperTrend Timeframe", group=grp_st_mode, tooltip="Select the timeframe for the SuperTrend. Default is Chart.")

string in_st_ma     = input.string(MA_VAWMA, title="MA Mode", options=[MA_SMA, MA_EMA, MA_WMA, MA_VWMA, MA_VAWMA], group=grp_st_man)
int    in_st_period = input.int(120, title="ATR Period", minval=1, group=grp_st_man)
float  in_st_mult   = input.float(3.0, title="Multiplier", minval=0.1, step=0.5, group=grp_st_man)
int    in_st_cb     = input.int(2, title="Closed Bars Confirm", minval=1, group=grp_st_man)

bool in_st_showSig  = input.bool(false, title="Show Buy/Sell Signals", group=grp_st_disp)

// ==============================================================================
// ━━━ SMC MODULE SETTINGS ━━━
// ==============================================================================
grp_smc_main  = "━━━ SMC: MAIN SETTINGS ━━━"
grp_smc_log   = "━━━ SMC: LOGIC & SENSITIVITY ━━━"
grp_smc_vis   = "━━━ SMC: VISUALS & ZONES ━━━"

bool showFVG   = input.bool(true, title="StormCore Auto: Show HTF FVG", group=grp_smc_main)
bool showOB    = input.bool(true, title="StormCore Auto: Show HTF OB", group=grp_smc_main)
bool showCHoCH = input.bool(true, title="StormCore Auto: Show HTF CHoCH", group=grp_smc_main)

int pivotLeft  = input.int(5, title="Pivot Left Bars", minval=1, group=grp_smc_log)
int pivotRight = input.int(3, title="Pivot Right Bars", minval=1, group=grp_smc_log)
int lookbackOB = input.int(50, title="Lookback for FVG/OB (Bars)", minval=10, group=grp_smc_log)
int maxHistory = input.int(15, title="Max Historical Setups", minval=1, maxval=40, group=grp_smc_log)

string posHTF    = input.string("Bottom Right", "HTF Dashboard Position", options=["Top Right", "Bottom Right", "Top Left", "Bottom Left"], group=grp_smc_vis)
color colOB_Bull = input.color(color.new(color.teal, 80), title="Bullish OB Color", group=grp_smc_vis)
color colOB_Bear = input.color(color.new(color.maroon, 80), title="Bearish OB Color", group=grp_smc_vis)
color colFVG_Bull= input.color(color.new(color.green, 85), title="Bullish FVG Color", group=grp_smc_vis)
color colFVG_Bear= input.color(color.new(color.red, 85), title="Bearish FVG Color", group=grp_smc_vis)
color colCHoCH   = input.color(#ffffffab, title="CHoCH Line Color", group=grp_smc_vis)

// ==============================================================================
// ━━━ DIV MODULE SETTINGS ━━━
// ==============================================================================
grp_div_main = "━━━ DIV: MAIN SETTINGS ━━━"
grp_div_ind  = "━━━ DIV: INDICATORS TOGGLES ━━━"
grp_div_vis  = "━━━ DIV: VISUALS & STYLES ━━━"

bool auto_mtf = input.bool(true, "StormCore Auto: MTF Dynamics", group=grp_div_main)
bool show_reg = input.bool(true, "StormCore Auto: Regular Divergences", group=grp_div_main)
bool show_hid = input.bool(true, "StormCore Auto: Hidden Divergences", group=grp_div_main)
int  prd      = input.int(5, "Pivot Period (Manual Mode)", minval=1, maxval=50, group=grp_div_main)
string src_type = input.string("Close", "Pivot Source", options=["Close", "High/Low"], group=grp_div_main)
int  min_divs = input.int(1, "Minimum Number of Divergence", minval=1, maxval=11, group=grp_div_main)
int  max_bars = input.int(100, "Maximum Bars to Check", minval=30, maxval=300, group=grp_div_main)
bool show_last= input.bool(false, "Show Only Last Divergence", group=grp_div_main)

bool use_macd  = input.bool(true, "MACD", group=grp_div_ind)
bool use_macdh = input.bool(true, "MACD Histogram", group=grp_div_ind)
bool use_rsi   = input.bool(true, "RSI", group=grp_div_ind)
bool use_stoch = input.bool(true, "Stochastic", group=grp_div_ind)
bool use_cci   = input.bool(true, "CCI", group=grp_div_ind)
bool use_mom   = input.bool(true, "Momentum", group=grp_div_ind)
bool use_obv   = input.bool(true, "OBV", group=grp_div_ind)
bool use_vwmacd= input.bool(true, "VW MACD", group=grp_div_ind)
bool use_cmf   = input.bool(true, "Chaikin Money Flow", group=grp_div_ind)
bool use_mfi   = input.bool(true, "Money Flow Index", group=grp_div_ind)
bool use_ext   = input.bool(false, "External Indicator", group=grp_div_ind)
float ext_src  = input.source(close, "External Source", group=grp_div_ind)

string show_indis = input.string("Don't Show", "Show Indicator Names", options=["Full", "First Letter", "Don't Show"], group=grp_div_vis)
bool show_num     = input.bool(true, "Show Divergence Number", group=grp_div_vis)
bool show_lines   = input.bool(false, "Draw Divergence Lines", group=grp_div_vis)
color pos_reg_col = input.color(color.yellow, "Positive Regular", group=grp_div_vis, inline="c1")
color neg_reg_col = input.color(color.navy, "Negative Regular", group=grp_div_vis, inline="c1")
color pos_hid_col = input.color(color.lime, "Positive Hidden", group=grp_div_vis, inline="c2")
color neg_hid_col = input.color(color.red, "Negative Hidden", group=grp_div_vis, inline="c2")
bool show_mas     = input.bool(false, "Show MAs (50 & 200)", group=grp_div_vis)
color ma50_col    = input.color(color.lime, "MA 50", group=grp_div_vis, inline="ma")
color ma200_col   = input.color(color.red, "MA 200", group=grp_div_vis, inline="ma")

// ==============================================================================
// ━━━ GLOBAL DATA STRUCTURES & VARIABLES ━━━
// ==============================================================================
type Pivot
    int bar
    float price

type DivSignal
    int type       
    int offset     
    string txt     
    color col
    int count      

type RenderSetup
    box   b_ob
    box   b_fvg
    line  l_ch
    label lb_ch
    bool  isActive
    int   dir
    float ob_mit_level
    float fvg_mit_level
    bool  ob_mitigated
    bool  fvg_mitigated

var ph_arr = array.new<Pivot>()
var pl_arr = array.new<Pivot>()
var active_lines  = array.new_line()
var active_labels = array.new_label()

var array<RenderSetup> setupPool = array.new<RenderSetup>()
var int currentSetupIdx = 0
var int activeSetupIdx = -1
var int lastProcessedSetupTime = na

if barstate.isfirst
    for i = 1 to maxHistory
        array.push(setupPool, RenderSetup.new(
             box.new(na,na,na,na, xloc=xloc.bar_time, border_color=color.new(color.white, 100)),
             box.new(na,na,na,na, xloc=xloc.bar_time, border_color=color.new(color.white, 100)),
             line.new(na,na,na,na, xloc=xloc.bar_time, style=line.style_dashed),
             label.new(na,na,"CHoCH", xloc=xloc.bar_time, style=label.style_label_left, size=size.small),
             false, 0, na, na, false, false
         ))

// ==============================================================================
// ━━━ METHODS & FUNCTIONS ━━━
// ==============================================================================

// --- DIV METHODS ---
get_name(string full, string short) =>
    show_indis == "Full" ? full : (show_indis == "First Letter" ? short : "")

method validate_slope(series float src, series float ind, int c_prd, int offset, int len, float p_price, float p_ind, bool is_low) =>
    bool is_clean = true
    float price_slope = (src[c_prd] - p_price) / len
    float ind_slope = (ind[c_prd] - p_ind) / len
    for j = 1 to len - 1
        int check_idx = c_prd + j
        float expected_price = src[c_prd] - (price_slope * j)
        float expected_ind = ind[c_prd] - (ind_slope * j)
        if is_low
            if src[check_idx] < expected_price or ind[check_idx] < expected_ind
                is_clean := false
                break
        else
            if src[check_idx] > expected_price or ind[check_idx] > expected_ind
                is_clean := false
                break
    is_clean

method check_div(series float src, series float ind, bool is_ph, bool is_pl, array<Pivot> p_highs, array<Pivot> p_lows, int c_prd, int max_b, bool check_reg, bool check_hid) =>
    bool pos_reg = false, bool neg_reg = false, bool pos_hid = false, bool neg_hid = false
    int opr = 0, int onr = 0, int oph = 0, int onh = 0
    if is_pl
        for p in p_lows
            int curr_bar = bar_index - c_prd
            int len = curr_bar - p.bar
            if len > max_b
                break
            if len > 5
                int offset = bar_index - p.bar
                float p_ind = ind[offset]
                if check_reg and src[c_prd] < p.price and ind[c_prd] > p_ind
                    if validate_slope(src, ind, c_prd, offset, len, p.price, p_ind, true)
                        pos_reg := true, opr := offset
                        break
                if check_hid and src[c_prd] > p.price and ind[c_prd] < p_ind
                    if validate_slope(src, ind, c_prd, offset, len, p.price, p_ind, true)
                        pos_hid := true, oph := offset
                        break
    if is_ph
        for p in p_highs
            int curr_bar = bar_index - c_prd
            int len = curr_bar - p.bar
            if len > max_b
                break
            if len > 5
                int offset = bar_index - p.bar
                float p_ind = ind[offset]
                if check_reg and src[c_prd] > p.price and ind[c_prd] < p_ind
                    if validate_slope(src, ind, c_prd, offset, len, p.price, p_ind, false)
                        neg_reg := true, onr := offset
                        break
                if check_hid and src[c_prd] < p.price and ind[c_prd] > p_ind
                    if validate_slope(src, ind, c_prd, offset, len, p.price, p_ind, false)
                        neg_hid := true, onh := offset
                        break
    [pos_reg, neg_reg, pos_hid, neg_hid, opr, onr, oph, onh]

method add_signal(array<DivSignal> arr, int type, int offset, string name, color col) =>
    bool found = false
    for s in arr
        if s.type == type and s.offset == offset
            if name != ""
                s.txt += (s.txt == "" ? "" : "\n") + name
            s.count += 1
            found := true
            break
    if not found
        arr.push(DivSignal.new(type, offset, name, col, 1))

method process_indicator(array<DivSignal> sigs, bool enabled, string name, series float src, series float ind, bool is_ph, bool is_pl, array<Pivot> phs, array<Pivot> pls, int c_prd, int mx, bool c_reg, bool c_hid) =>
    if enabled
        [pr, nr, ph, nh, opr, onr, oph, onh] = check_div(src, ind, is_ph, is_pl, phs, pls, c_prd, mx, c_reg, c_hid)
        if pr
            sigs.add_signal(0, opr, name, pos_reg_col)
        if nr
            sigs.add_signal(1, onr, name, neg_reg_col)
        if ph
            sigs.add_signal(2, oph, name, pos_hid_col)
        if nh
            sigs.add_signal(3, onh, name, neg_hid_col)

// --- SMC METHODS ---
getAutoHTF() =>
    bool isMins = timeframe.isminutes, bool isDaily = timeframe.isdaily, bool isWeekly = timeframe.isweekly
    int mult = timeframe.multiplier
    string htf = "1D" 
    if isMins
        if mult < 60
            htf := "60"
        else if mult >= 60 and mult <= 180
            htf := "240"
        else
            htf := "1D"
    else if isDaily
        htf := "1W"
    else if isWeekly
        htf := "1M"
    else
        htf := "1M"
    htf

calc_smc(int pLeft, int pRight, int lookback) =>
    float smc_ph = ta.pivothigh(high, pLeft, pRight)
    float smc_pl = ta.pivotlow(low, pLeft, pRight)
    var float lastSwingHighPrice = na, var int lastSwingHighTime = na
    var float lastSwingLowPrice = na, var int lastSwingLowTime = na

    if not na(smc_ph)
        lastSwingHighPrice := high[pRight]
        lastSwingHighTime  := time[pRight]
    if not na(smc_pl)
        lastSwingLowPrice := low[pRight]
        lastSwingLowTime  := time[pRight]

    var int trendDir = 1
    int activeDir = 0, float chochLvl = na, int chochT = na
    bool bearCHoCH = false, bool bullCHoCH = false

    if trendDir == 1 and not na(lastSwingLowPrice)
        if close < lastSwingLowPrice 
            trendDir := -1, chochLvl := lastSwingLowPrice, chochT := lastSwingLowTime, bearCHoCH := true
    else if trendDir == -1 and not na(lastSwingHighPrice)
        if close > lastSwingHighPrice 
            trendDir := 1, chochLvl := lastSwingHighPrice, chochT := lastSwingHighTime, bullCHoCH := true

    float oTop = na, float oBot = na, int oTime = na
    float fTop = na, float fBot = na, int fTime = na

    if bearCHoCH
        bool fFVG = false, bool fOB = false
        for i = 1 to lookback
            if high[i] < low[i+2] and close[i+1] < open[i+1]
                fTop := low[i+2], fBot := high[i], fTime := time[i+2]
                fFVG := true
                break
        for i = 1 to lookback
            if close[i] > open[i] and time[i] <= lastSwingHighTime
                oTop := high[i], oBot := low[i], oTime := time[i]
                fOB := true
                break
        if fFVG and fOB
            activeDir := -1

    if bullCHoCH
        bool fFVG = false, bool fOB = false
        for i = 1 to lookback
            if low[i] > high[i+2] and close[i+1] > open[i+1]
                fTop := low[i], fBot := high[i+2], fTime := time[i+2]
                fFVG := true
                break
        for i = 1 to lookback
            if close[i] < open[i] and time[i] <= lastSwingLowTime
                oTop := high[i], oBot := low[i], oTime := time[i]
                fOB := true
                break
        if fFVG and fOB
            activeDir := 1

    [activeDir, oTop, oBot, oTime, fTop, fBot, fTime, chochLvl, chochT]

// --- SUPERTREND METHODS ---
core_st_logic() =>
    int tf_seconds = timeframe.in_seconds(timeframe.period)
    string active_ma = in_st_ma
    int active_period = in_st_period
    float active_mult = in_st_mult
    int active_cb = in_st_cb
    
    if in_st_opMode == MODE_AUTO
        if tf_seconds < 86400
            active_ma := MA_VAWMA, active_period := 50, active_mult := 3.0, active_cb := 2
        else if tf_seconds >= 86400 and tf_seconds < 604800
            active_ma := MA_VAWMA, active_period := 100, active_mult := 4.0, active_cb := 2
        else
            active_ma := MA_VAWMA, active_period := 120, active_mult := 5.0, active_cb := 2

    float vol = nz(volume, 1)
    float tr_val = ta.tr(true)
    float atr_val = na
    switch active_ma
        MA_SMA   => atr_val := ta.sma(tr_val, active_period)
        MA_EMA   => atr_val := ta.ema(tr_val, active_period)
        MA_WMA   => atr_val := ta.wma(tr_val, active_period)
        MA_VWMA  => atr_val := ta.vwma(tr_val, active_period)
        MA_VAWMA => atr_val := ta.wma(tr_val * vol, active_period) / ta.wma(vol, active_period)
        => atr_val := ta.sma(tr_val, active_period)
    
    float hl2 = math.avg(high, low)
    float basic_up = hl2 + (active_mult * atr_val)
    float basic_dn = hl2 - (active_mult * atr_val)

    float upper = na, float lower = na
    int trend = na, int bars_above = na, int bars_below = na
    
    upper := nz(upper[1], basic_up)
    lower := nz(lower[1], basic_dn)
    trend := nz(trend[1], 1)
    bars_above := nz(bars_above[1], 0)
    bars_below := nz(bars_below[1], 0)
    
    if trend == -1
        if close > upper
            bars_above += 1
        else
            bars_above := 0 
    else if trend == 1
        if close < lower
            bars_below += 1
        else
            bars_below := 0
            
    bool flip_to_bull = trend == -1 and bars_above >= active_cb
    bool flip_to_bear = trend == 1 and bars_below >= active_cb
    
    if flip_to_bull
        trend := 1, bars_above := 0, lower := basic_dn 
    else if flip_to_bear
        trend := -1, bars_below := 0, upper := basic_up 
        
    if trend == 1 and not flip_to_bull
        lower := basic_dn > lower ? basic_dn : lower
    else if trend == -1 and not flip_to_bear
        upper := basic_up < upper ? basic_up : upper
        
    [upper, lower, trend]


// ==============================================================================
// ━━━ LOGIC EXECUTION ENGINE ━━━
// ==============================================================================

// --- 1. SUPERTREND EXECUTION ---
[htf_upper, htf_lower, htf_trend] = request.security(syminfo.tickerid, in_st_tf, core_st_logic(), barmerge.gaps_off, barmerge.lookahead_off)
bool is_buy = htf_trend == 1 and nz(htf_trend[1], 1) == -1
bool is_sell = htf_trend == -1 and nz(htf_trend[1], 1) == 1

// --- 2. SMC EXECUTION ---
string targetHTF = getAutoHTF()
[sigDir, obT, obB, obTime, fvgT, fvgB, fvgTime, chLvl, chTime] = request.security(syminfo.tickerid, targetHTF, calc_smc(pivotLeft, pivotRight, lookbackOB), barmerge.gaps_off, barmerge.lookahead_off)

if show_mod_smc
    if sigDir != 0 and (na(lastProcessedSetupTime) or obTime != lastProcessedSetupTime)
        lastProcessedSetupTime := obTime
        currentSetupIdx := (currentSetupIdx + 1) % maxHistory
        activeSetupIdx := currentSetupIdx
        RenderSetup rs = array.get(setupPool, currentSetupIdx)
        
        color obColor  = sigDir == 1 ? colOB_Bull : colOB_Bear
        color fvgColor = sigDir == 1 ? colFVG_Bull : colFVG_Bear
        
        rs.isActive := true, rs.dir := sigDir
        rs.ob_mitigated := false, rs.fvg_mitigated := false
        rs.ob_mit_level  := sigDir == 1 ? obT : obB 
        rs.fvg_mit_level := sigDir == 1 ? fvgT : fvgB 
        
        if showOB
            rs.b_ob.set_lefttop(obTime, obT), rs.b_ob.set_rightbottom(time, obB), rs.b_ob.set_bgcolor(obColor)
        else
            rs.b_ob.set_lefttop(na, na), rs.b_ob.set_rightbottom(na, na)
            
        if showFVG
            rs.b_fvg.set_lefttop(fvgTime, fvgT), rs.b_fvg.set_rightbottom(time, fvgB), rs.b_fvg.set_bgcolor(fvgColor)
        else
            rs.b_fvg.set_lefttop(na, na), rs.b_fvg.set_rightbottom(na, na)
    
        if showCHoCH
            rs.l_ch.set_xy1(chTime, chLvl), rs.l_ch.set_xy2(time, chLvl), rs.l_ch.set_color(colCHoCH)
            rs.lb_ch.set_xy(time, chLvl), rs.lb_ch.set_textcolor(colCHoCH), rs.lb_ch.set_color(color.new(color.white, 100))
        else
            rs.l_ch.set_xy1(na, na), rs.l_ch.set_xy2(na, na), rs.lb_ch.set_xy(na, na)
    
    if array.size(setupPool) > 0
        for i = 0 to maxHistory - 1
            RenderSetup rs = array.get(setupPool, i)
            if rs.isActive
                if not rs.ob_mitigated
                    bool isHitOB = false
                    if rs.dir == 1 and low <= rs.ob_mit_level
                        isHitOB := true
                    else if rs.dir == -1 and high >= rs.ob_mit_level
                        isHitOB := true
                    if isHitOB
                        rs.ob_mitigated := true
                    if showOB
                        rs.b_ob.set_right(time)
                
                if not rs.fvg_mitigated
                    bool isHitFVG = false
                    if rs.dir == 1 and low <= rs.fvg_mit_level
                        isHitFVG := true
                    else if rs.dir == -1 and high >= rs.fvg_mit_level
                        isHitFVG := true
                    if isHitFVG
                        rs.fvg_mitigated := true
                    if showFVG
                        rs.b_fvg.set_right(time)
    
    if activeSetupIdx != -1
        RenderSetup activeRS = array.get(setupPool, activeSetupIdx)
        if showCHoCH
            activeRS.lb_ch.set_x(time)
            activeRS.l_ch.set_x2(time)

// --- 3. DIVERGENCE EXECUTION ---
int calc_prd = prd
bool disable_calc = false
if auto_mtf
    if timeframe.ismonthly
        calc_prd := 2
    else if timeframe.isweekly
        calc_prd := 4
    else if timeframe.isdaily
        calc_prd := 20
    else if timeframe.isintraday
        disable_calc := true

float eval_src_high = src_type == "Close" ? close : high
float eval_src_low  = src_type == "Close" ? close : low
float eval_src      = src_type == "Close" ? close : hl2

float div_ph = ta.pivothigh(eval_src_high, calc_prd, calc_prd)
float div_pl = ta.pivotlow(eval_src_low, calc_prd, calc_prd)
bool new_ph = not na(div_ph) and not disable_calc
bool new_pl = not na(div_pl) and not disable_calc

float rsi_val   = ta.rsi(close, 14)
[macd_line, sig_line, macd_hist] = ta.macd(close, 12, 26, 9)
float stoch_val = ta.sma(ta.stoch(close, high, low, 14), 3)
float cci_val   = ta.cci(close, 10)
float mom_val   = ta.mom(close, 10)
float obv_val   = ta.cum(math.sign(ta.change(close)) * volume)
float vwmacd_val= ta.vwma(close, 12) - ta.vwma(close, 26)
float cmf_val   = ta.sma(((close-low) - (high-close)) / (high - low == 0 ? 1 : high - low) * volume, 21) / ta.sma(volume, 21)
float mfi_val   = ta.mfi(close, 14)
float ext_val   = ext_src

DivSignal[] current_signals = array.new<DivSignal>()

if show_mod_div and (new_pl or new_ph) and not disable_calc
    current_signals.process_indicator(use_macd,  get_name("MACD", "M"), eval_src, macd_line, new_ph, new_pl, ph_arr, pl_arr, calc_prd, max_bars, show_reg, show_hid)
    current_signals.process_indicator(use_macdh, get_name("Hist", "H"), eval_src, macd_hist, new_ph, new_pl, ph_arr, pl_arr, calc_prd, max_bars, show_reg, show_hid)
    current_signals.process_indicator(use_rsi,   get_name("RSI",  "R"), eval_src, rsi_val,   new_ph, new_pl, ph_arr, pl_arr, calc_prd, max_bars, show_reg, show_hid)
    current_signals.process_indicator(use_stoch, get_name("Stoch","S"), eval_src, stoch_val, new_ph, new_pl, ph_arr, pl_arr, calc_prd, max_bars, show_reg, show_hid)
    current_signals.process_indicator(use_cci,   get_name("CCI",  "C"), eval_src, cci_val,   new_ph, new_pl, ph_arr, pl_arr, calc_prd, max_bars, show_reg, show_hid)
    current_signals.process_indicator(use_mom,   get_name("Mom",  "M"), eval_src, mom_val,   new_ph, new_pl, ph_arr, pl_arr, calc_prd, max_bars, show_reg, show_hid)
    current_signals.process_indicator(use_obv,   get_name("OBV",  "O"), eval_src, obv_val,   new_ph, new_pl, ph_arr, pl_arr, calc_prd, max_bars, show_reg, show_hid)
    current_signals.process_indicator(use_vwmacd,get_name("VWM",  "V"), eval_src, vwmacd_val,new_ph, new_pl, ph_arr, pl_arr, calc_prd, max_bars, show_reg, show_hid)
    current_signals.process_indicator(use_cmf,   get_name("CMF",  "C"), eval_src, cmf_val,   new_ph, new_pl, ph_arr, pl_arr, calc_prd, max_bars, show_reg, show_hid)
    current_signals.process_indicator(use_mfi,   get_name("MFI",  "M"), eval_src, mfi_val,   new_ph, new_pl, ph_arr, pl_arr, calc_prd, max_bars, show_reg, show_hid)
    current_signals.process_indicator(use_ext,   get_name("Ext",  "X"), eval_src, ext_val,   new_ph, new_pl, ph_arr, pl_arr, calc_prd, max_bars, show_reg, show_hid)
    
    if new_ph
        ph_arr.unshift(Pivot.new(bar_index[calc_prd], div_ph))
        if ph_arr.size() > 15
            ph_arr.pop()
    if new_pl
        pl_arr.unshift(Pivot.new(bar_index[calc_prd], div_pl))
        if pl_arr.size() > 15
            pl_arr.pop()

// ==============================================================================
// ━━━ GLOBAL RENDERING & ALERTS ━━━
// ==============================================================================

// --- ST RENDERING ---
float upPlotLine = show_mod_st and htf_trend == 1 ? htf_lower : na
float dnPlotLine = show_mod_st and htf_trend == -1 ? htf_upper : na

plot(upPlotLine, title="Up Trend (HTF)", color=color.green, style=plot.style_linebr, linewidth=2)
plot(dnPlotLine, title="Down Trend (HTF)", color=color.red, style=plot.style_linebr, linewidth=2)

plotshape(show_mod_st and is_buy and in_st_showSig ? htf_lower : na, title="Buy Signal", text="Buy", location=location.absolute, style=shape.labelup, size=size.tiny, color=color.green, textcolor=color.white)
plotshape(show_mod_st and is_sell and in_st_showSig ? htf_upper : na, title="Sell Signal", text="Sell", location=location.absolute, style=shape.labeldown, size=size.tiny, color=color.red, textcolor=color.white)
plotshape(show_mod_st and is_buy and not in_st_showSig ? htf_lower : na, title="Buy Dot", location=location.absolute, style=shape.circle, size=size.tiny, color=color.green)
plotshape(show_mod_st and is_sell and not in_st_showSig ? htf_upper : na, title="Sell Dot", location=location.absolute, style=shape.circle, size=size.tiny, color=color.red)

// --- SMC DASHBOARD ---
string realPos = posHTF == "Top Right" ? position.top_right : posHTF == "Bottom Right" ? position.bottom_right : posHTF == "Top Left" ? position.bottom_left : position.bottom_left
var table htfTable = table.new(realPos, 1, 1, bgcolor=color.new(color.black, 40), frame_color=color.new(color.gray, 70), frame_width=1)
if barstate.islast and show_mod_smc
    table.cell(htfTable, 0, 0, "STORMCORE HTF: " + targetHTF, text_color=color.new(color.white, 10), text_size=size.small)
else if barstate.islast and not show_mod_smc
    table.clear(htfTable, 0, 0)

// --- DIV RENDERING ---
if show_mod_div
    if show_last and current_signals.size() > 0
        for ln in active_lines
            ln.delete()
        for lb in active_labels
            lb.delete()
        active_lines.clear()
        active_labels.clear()

    for s in current_signals
        if s.count >= min_divs
            float y1 = src_type == "Close" ? close[s.offset] : (s.type == 0 or s.type == 2 ? low[s.offset] : high[s.offset])
            float y2 = src_type == "Close" ? close[calc_prd] : (s.type == 0 or s.type == 2 ? low[calc_prd] : high[calc_prd])
            
            line ln = show_lines ? line.new(bar_index - s.offset, y1, bar_index - calc_prd, y2, color=s.col, width=2, style= s.type <= 1 ? line.style_solid : line.style_dashed) : na
            
            string final_txt = s.txt
            if show_num
                final_txt += (final_txt == "" ? "" : "\n") + str.tostring(s.count)
                
            label lb = na
            if final_txt != ""
                if s.type == 0 or s.type == 2
                    lb := label.new(bar_index - calc_prd, low[calc_prd], text=final_txt, color=s.col, style=label.style_label_up, size=size.small, textcolor=color.black)
                else
                    lb := label.new(bar_index - calc_prd, high[calc_prd], text=final_txt, color=s.col, style=label.style_label_down, size=size.small, textcolor=color.white)
                    
            if show_last
                if not na(ln)
                    active_lines.push(ln)
                if not na(lb)
                    active_labels.push(lb)

plot(show_mod_div and show_mas ? ta.sma(close, 50)  : na, title="MA 50",  color=ma50_col,  linewidth=2)
plot(show_mod_div and show_mas ? ta.sma(close, 200) : na, title="MA 200", color=ma200_col, linewidth=2)

// --- ALERTS COMPILATION ---
bool a_pos_reg = false, bool a_neg_reg = false, bool a_pos_hid = false, bool a_neg_hid = false
for s in current_signals
    if s.count >= min_divs
        if s.type == 0
            a_pos_reg := true
        if s.type == 1
            a_neg_reg := true
        if s.type == 2
            a_pos_hid := true
        if s.type == 3
            a_neg_hid := true

alertcondition(is_buy, title="SC Master: ST+ Buy Signal", message="SC Master: SuperTrend BUY at {{close}} ({{ticker}} {{interval}})")
alertcondition(is_sell, title="SC Master: ST+ Sell Signal", message="SC Master: SuperTrend SELL at {{close}} ({{ticker}} {{interval}})")
alertcondition(a_pos_reg, title="SC Master: Pos. Regular Div", message="SC Master: Positive Regular Divergence")
alertcondition(a_neg_reg, title="SC Master: Neg. Regular Div", message="SC Master: Negative Regular Divergence")
alertcondition(a_pos_hid, title="SC Master: Pos. Hidden Div",  message="SC Master: Positive Hidden Divergence")
alertcondition(a_neg_hid, title="SC Master: Neg. Hidden Div",  message="SC Master: Negative Hidden Divergence")

// ==============================================================================
// ━━━ EOF ━━━
// ==============================================================================
